package de.xelerity.geolessi.servlet;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.xelerity.geolessi.preferences.Preferences;
import de.xelerity.geolessi.srv.InfoProvider;
import de.xelerity.geolessi.srv.poi.HalteStelleNextAbfahrtGetterI;
import de.xelerity.geolessi.types.poi.NextAbfahrtInfo;
import de.xelerity.helper.StringFunktionen;

public class GetHSNextAbfahrt extends HttpServlet {

	private static final long serialVersionUID = -8426966764258759L;
	private static Log log = LogFactory.getLog(GetHSNextAbfahrt.class);

	private class WSInput {
		public long currenttime = 0L;
		public ArrayList<String> hsids = null;
		public long haltestelletype = 0L;
	}

	private WSInput parseInput(HttpServletRequest request) throws Exception {
		if (request == null)
			throw new IllegalArgumentException("request==null");

		WSInput wsinput = new WSInput();

		String haltestelletype = request.getParameter("hstype");
		if (StringFunktionen.isEmptyTrimed(haltestelletype)) {
			throw new IllegalArgumentException("Invalid Parameter: 'hstype' para did not exists");
		}
		if (!haltestelletype.trim().matches("[0-9]+")) {
			throw new IllegalArgumentException("Invalid Parameter: 'hstype' para is not a number");
		}
		wsinput.haltestelletype = Long.parseLong(haltestelletype.trim());

		String time = request.getParameter("time");
		if (StringFunktionen.isEmptyTrimed(time)) {
			throw new IllegalArgumentException("Invalid Parameter: 'time' para did not exists");
		}
		if (!time.trim().matches("[0-9]+")) {
			throw new IllegalArgumentException("Invalid Parameter: 'time' para is not a number");
		}
		wsinput.currenttime = Long.parseLong(time.trim());

		String[] parameterValues = request.getParameterValues("hs");

		if (parameterValues == null || parameterValues.length == 0) {
			throw new IllegalArgumentException("Invalid Parameter: 'hs' para(s) is(are) not a defined");
		}

		wsinput.hsids = new ArrayList<String>();
		Set<String> hash = new HashSet<String>();
		for (String id : parameterValues) {
			if (!id.trim().matches("[0-9]+")) {
				throw new IllegalArgumentException("Invalid Parameter: 'hs' is no number");
			}
			hash.add(id.trim());
		}
		wsinput.hsids.addAll(hash);

		return wsinput;
	}

	// geolessiprovider.appspot.com/getnxtab?hs=559557&time=1344454853607
	private void doService(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		try {

			WSInput parseInput = parseInput(request);

			HalteStelleNextAbfahrtGetterI halteStelleNextAbfahrtProvider = InfoProvider.getHalteStelleNextAbfahrtProvider();

			// Aktuelle uebergebene Orts-Zeit der Serverzeit anpassen
			parseInput.currenttime += Preferences.ServerTimeOffset;

			List<NextAbfahrtInfo> nextAbfahrten = halteStelleNextAbfahrtProvider.getNextAbfahrten(parseInput.hsids,
					parseInput.haltestelletype, parseInput.currenttime);

			writeRet(request, response, nextAbfahrten);

		} catch (Throwable e) {
			WSErrorJs wse = new WSErrorJs();
			wse.error = e.getMessage();
			writeRet(request, response, wse);
			log.error("Fehler bei Ausfuehrung des Request:" + e.getMessage());
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doService(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doService(request, response);
	}

	// public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
	//
	// /*
	// * http://geolessiprovider.appspot.com/t2
	// */
	// try {
	// MemcacheService syncCache = MemcacheServiceFactory.getMemcacheService();
	// // syncCache.setNamespace("d");
	// // syncCache.setErrorHandler(ErrorHandlers.getConsistentLogAndContinue(Level.INFO));
	//
	// syncCache.put("d", "oliver");
	//
	// Object object = syncCache.get("d");
	//
	// Log log = LogFactory.getLog(T2Servlet.class);
	//
	// log.error("error");
	// log.warn("warning");
	// log.info("info");
	// log.debug("debug");
	// log.fatal("fatal");
	//
	// resp.setContentType("text/plain");
	// resp.getWriter().println("Hello, world1:" + object);
	// } catch (Throwable w) {
	// resp.setContentType("text/plain");
	// resp.getWriter().println("Hello, world5:" + w + "::" + w.getMessage());
	// }
	//
	// }

	private void writeRet(HttpServletRequest pRequest, HttpServletResponse pResponse, Object pRes) {
		if (pRes == null) {
			WSErrorJs wse = new WSErrorJs();
			wse.error = "Argument to writeRet == <null>";
			pRes = wse;
		}

		try {
			OutputStream lOutputStream = (OutputStream) pResponse.getOutputStream();
			pResponse.setHeader("Content-Type", "application/json; charset=utf-8");
			pResponse.setCharacterEncoding(de.xelerity.geolessi.preferences.Preferences.ENC_UTF);
			ObjectMapper om = new ObjectMapper();

			if (lOutputStream != null) {
				om.writeValue(lOutputStream, pRes);
				lOutputStream.flush();
				lOutputStream.close();
			}

			HttpSession lSession = pRequest.getSession(false);
			if (lSession != null) {
				lSession.invalidate();
			}
		} catch (Throwable e) {
			log.error("Fehler beim Schreiben des OutputStreams:" + e.getMessage());
		}
	}
}
